#include "commands.h"
#include "hashtables.h"
#include "extern.h"
#include "errors.h"
#include "net.h"
#include "users.h"
#include "channels.h"

void process_message (Client *me,  Message msg){

	me = NULL;
	msg.tail[0] = 0;
}

int command_add (const char *cmdname, void (*go)(Client*me, char tail[TAILSIZE]), int level)
{
 Command *cmd = NULL;
 int gard;
	
	cmd = malloc (sizeof (Command));
	if (cmd != NULL)
	{
		strncpy (cmd->cmd, cmdname, CMDSIZE);
		cmd->level = level;
		cmd->go = go;

		gard = HashTable_Insert (commandstb, cmd, cmdname);
		if (gard == -1)
		{
			printf ("AddCommand: error inserting command into commandstb\n");
		}
	}
	else
	{
		printf ("AddCommand: unable to malloc\n");
	}


 return 0;
}

int command_add_all (void){

	command_add ("kick", 	command_kick, 		COMMAND_LEVELALL);
	command_add ("create", 	command_create, 	COMMAND_LEVELALL);
	command_add ("profile",   command_profile,		COMMAND_LEVELALL);
	command_add ("ban", 	command_ban, 		COMMAND_LEVELALL);
	command_add ("part", 	command_part, 		COMMAND_LEVELALL);

 	return 0;
}

void command_del_all (void){

	command_del ("kick");
	command_del ("create");
	command_del ("profile");
	command_del ("ban");
	command_del ("part");
}

void command_del (const char* cmdname)
{
	HashTable_Remove (commandstb, cmdname);
}


/* built in commands */

void command_kick (Client *me, char tail[TAILSIZE])
/*
	KICK <nick> <by> <chan> <reason>
*/
{
	Channel* chan = NULL;
	ChannelClient* chclient = NULL;
	Client *usr = NULL;
	char reason[REASONSIZE],
		 by[NICKSIZE],
		 schan[TABLENAMESIZE],
		 kicknick[NICKSIZE];
	int gard;

	gard = sscanf (tail, "%16s %16s %32s %32[^\n]", kicknick, by, schan, reason);
	if (gard != 4){
		gard = SendToClient (me, "%d %s", ENUM_400, EBADREQUEST);
			if (gard == -2){
				KillClient (me->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
	else
	{
		chan = HashTable_Find (channelstb, schan);
		if (chan == NULL){
			gard = SendToClient (me, "%d %s", ENUM_418, ENOSUCHTABLE);
				if (gard == -2){
					KillClient (me->user, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
		else
		{
			chclient = chan_member_find(chan, me->user);
			if ((chclient != NULL) && (chclient->level == USERLEVEL_OP)){
				gard = SendToClient (me, "%d %s", ENUM_414, ENOTANOWNER);
					if (gard == -2){
						KillClient (me->user, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
			else
			{
				usr = HashTable_Find (clientstb, kicknick);
				if ((usr == NULL) || (chan_member_find (chan, kicknick) == NULL)){
					gard = SendToClient (me, "%d %s", ENUM_401, ENOSUCHNICK);
						if (gard == -2){
							KillClient (me->user, "broken pipe");
						}
						if (gard == -1)
							printf("error send()\n");
				}
				else
				{
					if (! USER_ISNOLEVEL(usr)){
						gard = SendToClient (me, "%d %s", ENUM_406, EADMINKICK);
							if (gard == -2){
								KillClient (me->user, "broken pipe");
							}
							if (gard == -1)
								printf("error send()\n");
					}
					else
					{
						SendToChan (chan, "KICK %s %s %s %s", kicknick, by, chan->name, reason);
						chan_member_del (chan, kicknick);
						client_chan_del (usr, chan->name);
					}
				}
			}
		}
	}
}

void command_ban (Client *me, char tail[TAILSIZE])
/*
	BAN <nick> <by> <chan> <reason>
*/
{
	Channel* chan = NULL;
	Client *usr = NULL;
	char reason[REASONSIZE],
		 by[NICKSIZE],
		 schan[TABLENAMESIZE],
		 bannick[NICKSIZE];
	int gard;
	BlackList *bl = NULL;
	ChannelClient *chclient = NULL;

	gard = sscanf (tail, "%16s %16s %32s %32[^\n]", bannick, by, schan, reason);
	if (gard != 4){
		gard = SendToClient (me, "%d %s", ENUM_400, EBADREQUEST);
			if (gard == -2){
				KillClient (me->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
	else
	{
		bl = malloc (sizeof (*bl));
		if (bl == NULL){
			fprintf (stderr, "error malloc\n");
		}
		else
		{
			chan = HashTable_Find (channelstb, schan);
			if (chan == NULL){
				gard = SendToClient (me, "%d %s", ENUM_418, ENOSUCHTABLE);
					if (gard == -2){
						KillClient (me->user, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
			else
			{
			chclient = chan_member_find(chan, me->user);
			if ((chclient != NULL) && (chclient->level == USERLEVEL_OP)){
					gard = SendToClient (me, "%d %s", ENUM_414, ENOTANOWNER);
						if (gard == -2){
							KillClient (me->user, "broken pipe");
						}
						if (gard == -1)
							printf("error send()\n");
				}
				else
				{
					usr = HashTable_Find (clientstb, bannick);
					if (usr == NULL){
						gard = SendToClient (me, "%d %s", ENUM_401, ENOSUCHNICK);
							if (gard == -2){
								KillClient (me->user, "broken pipe");
							}
							if (gard == -1)
								printf("error send()\n");
					}
					else
					{
						if (! USER_ISNOLEVEL(usr)){
							gard = SendToClient (me, "%d %s", ENUM_410, EBANNADMIN);
								if (gard == -2){
									KillClient (me->user, "broken pipe");
								}
								if (gard == -1)
									printf("error send()\n");
						}
						else
						{
							SendToChan (chan, "BAN %s %s %s %s", bannick, by, chan->name, reason);
							strcpy (bl->nick, usr->nick);
							strcpy (bl->user, usr->user);
							strcpy (bl->host, usr->host);
							chan_ban_add (chan, bl);
						}
					}
				}
			}
		}
	}
}

void command_create (Client *suser, char tail[TAILSIZE])
/*
	
*/
{
/* "name status chairs mincash blind desc" */

 char name[TABLENAMESIZE],
      desc[TABLEDESCSIZE];
  Channel *newchan = NULL;
 int gard;


	if (suser->owntb == 0){
		gard = sscanf (tail, "%32s %128[^\n]", (char*)&name, (char*)&desc);
			if (gard == 2){
				newchan = malloc (sizeof (*newchan));
					if (newchan == NULL){
						fprintf (stderr, "malloc error\n");
					}
					else
					{
						newchan = chan_new (name, desc, CHANMODE_DEFAULT, suser->id);
						chan_add (newchan);

						gard = SendToClient (suser, "Created !\r\n");
							if (gard == -2){
								KillClient (suser->user, "broken pipe");
							}
							if (gard == -1)
								printf("error send()\n");
					}
			}
			else
			{
				gard = SendToClient (suser, "bad request\r\n");
					if (gard == -2){
						KillClient (suser->user, "broken pipe");
					}
					if (gard == -1)
						printf("error send()\n");
			}
	}
	else
	{
		gard = SendToClient (suser, "%d %s", ENUM_428, EALREADYOWNER);
			if (gard == -2){
				KillClient (suser->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}

void command_profile (Client *me, char tail[TAILSIZE])
/*
	
*/
{
  Client *user = NULL;
  int gard;

	user = HashTable_Find (clientstb, tail);
	if (user != NULL){
		gard = SendToClient (me, "PROFILE %s %s\r\n", user->nick, user->user, user->host);
			if (gard == -2){
				KillClient (me->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
	else
	{
		gard = SendToClient (me, "%d %s", ENUM_401, ENOSUCHNICK);
			if (gard == -2){
				KillClient (me->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}

void command_part (Client *me, char tail[TAILSIZE])
/*
	
*/
{
  Channel *chan = NULL;
  int gard;

	chan = HashTable_Find (channelstb, tail);
	if (chan != NULL){
		if (chan_member_find (chan, me->nick) != NULL){
			chan_member_del (chan, me->user);
			client_chan_del (me, chan->name);
			SendToChan (chan, "PART %s", me->user);
		}
		else
		{
			gard = SendToClient (me, "You aren't on this table\r\n");
				if (gard == -2){
					KillClient (me->user, "broken pipe");
				}
				if (gard == -1)
					printf("error send()\n");
		}
	}
	else
	{
		gard = SendToClient (me, "%d %s", ENUM_418, ENOSUCHTABLE);
			if (gard == -2){
				KillClient (me->user, "broken pipe");
			}
			if (gard == -1)
				printf("error send()\n");
	}
}
